#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
通用三级左侧菜单生成器
Universal Three-Level Sidebar Menu Generator

专门为通用项目设计的菜单生成系统，支持标准的三级菜单结构
"""

import json
import os
import re
from enum import Enum
from dataclasses import dataclass
from typing import List, Dict, Any, Optional

class FrameworkType(Enum):
    """支持的前端框架"""
    VUE_ELEMENT = "vue_element"
    VUE_ANTD = "vue_antd" 
    REACT_ANTD = "react_antd"

@dataclass
class UniversalMenuConfig:
    """通用菜单配置"""
    framework: FrameworkType = FrameworkType.VUE_ELEMENT
    output_dir: str = "generated_menu"
    component_name: str = "SidebarMenu"
    enable_icons: bool = True
    enable_collapse: bool = True
    enable_search: bool = False
    theme: str = "light"  # light, dark
    max_levels: int = 3   # 最大层级数

class UniversalMenuGenerator:
    """通用菜单生成器"""
    
    def __init__(self, config: UniversalMenuConfig):
        self.config = config
        
    def create_sample_data(self) -> List[Dict]:
        """创建标准的三级菜单示例数据"""
        return [
            {
                "id": 1,
                "title": "仪表盘",
                "path": "/dashboard",
                "icon": "dashboard",
                "children": []
            },
            {
                "id": 2,
                "title": "用户管理",
                "path": "/user",
                "icon": "user",
                "children": [
                    {
                        "id": 21,
                        "title": "用户列表",
                        "path": "/user/list",
                        "icon": "list",
                        "children": []
                    },
                    {
                        "id": 22,
                        "title": "角色管理",
                        "path": "/user/role",
                        "icon": "role",
                        "children": [
                            {
                                "id": 221,
                                "title": "角色列表",
                                "path": "/user/role/list",
                                "icon": "list"
                            },
                            {
                                "id": 222,
                                "title": "权限分配",
                                "path": "/user/role/permission",
                                "icon": "permission"
                            }
                        ]
                    },
                    {
                        "id": 23,
                        "title": "部门管理",
                        "path": "/user/department",
                        "icon": "department",
                        "children": []
                    }
                ]
            },
            {
                "id": 3,
                "title": "内容管理",
                "path": "/content",
                "icon": "content",
                "children": [
                    {
                        "id": 31,
                        "title": "文章管理",
                        "path": "/content/article",
                        "icon": "article",
                        "children": [
                            {
                                "id": 311,
                                "title": "文章列表",
                                "path": "/content/article/list",
                                "icon": "list"
                            },
                            {
                                "id": 312,
                                "title": "分类管理",
                                "path": "/content/article/category",
                                "icon": "category"
                            }
                        ]
                    },
                    {
                        "id": 32,
                        "title": "媒体库",
                        "path": "/content/media",
                        "icon": "media",
                        "children": []
                    }
                ]
            },
            {
                "id": 4,
                "title": "系统设置",
                "path": "/system",
                "icon": "setting",
                "children": [
                    {
                        "id": 41,
                        "title": "基础配置",
                        "path": "/system/config",
                        "icon": "config",
                        "children": []
                    },
                    {
                        "id": 42,
                        "title": "日志管理",
                        "path": "/system/log",
                        "icon": "log",
                        "children": [
                            {
                                "id": 421,
                                "title": "操作日志",
                                "path": "/system/log/operation",
                                "icon": "operation"
                            },
                            {
                                "id": 422,
                                "title": "错误日志",
                                "path": "/system/log/error",
                                "icon": "error"
                            }
                        ]
                    }
                ]
            }
        ]
    
    def generate_vue_element_menu(self, menu_data: List[Dict]) -> str:
        """生成Vue + Element Plus菜单组件"""
        return f'''<template>
  <div class="sidebar-menu">
    <el-menu
      :default-active="activeMenu"
      class="el-menu-vertical"
      :collapse="isCollapse"
      background-color="{self._get_bg_color()}"
      text-color="{self._get_text_color()}"
      active-text-color="{self._get_active_color()}"
      @select="handleMenuSelect"
    >
      <template v-for="item in menuData" :key="item.id">
        <sidebar-menu-item :menu-item="item" />
      </template>
    </el-menu>
  </div>
</template>

<script setup>
import {{ ref, computed }} from 'vue'
import {{ useRouter, useRoute }} from 'vue-router'
import SidebarMenuItem from './SidebarMenuItem.vue'

const props = defineProps({{
  collapse: {{
    type: Boolean,
    default: false
  }}
}})

const router = useRouter()
const route = useRoute()

const isCollapse = computed(() => props.collapse)
const activeMenu = computed(() => route.path)

const menuData = {json.dumps(menu_data, ensure_ascii=False, indent=2)}

const handleMenuSelect = (path) => {{
  router.push(path)
}}
</script>

<style scoped>
.sidebar-menu {{
  height: 100vh;
  overflow-y: auto;
}}

.el-menu-vertical {{
  border-right: none;
}}

.el-menu-vertical:not(.el-menu--collapse) {{
  width: 240px;
}}
</style>'''

    def generate_vue_menu_item(self) -> str:
        """生成Vue菜单项组件"""
        return '''<template>
  <div>
    <!-- 没有子菜单的项目 -->
    <el-menu-item
      v-if="!hasChildren"
      :index="menuItem.path"
      @click="handleClick"
    >
      <el-icon v-if="menuItem.icon">
        <component :is="getIconComponent(menuItem.icon)" />
      </el-icon>
      <template #title>
        <span>{{ menuItem.title }}</span>
      </template>
    </el-menu-item>

    <!-- 有子菜单的项目 -->
    <el-sub-menu
      v-else
      :index="menuItem.path"
    >
      <template #title>
        <el-icon v-if="menuItem.icon">
          <component :is="getIconComponent(menuItem.icon)" />
        </el-icon>
        <span>{{ menuItem.title }}</span>
      </template>
      
      <sidebar-menu-item
        v-for="child in menuItem.children"
        :key="child.id"
        :menu-item="child"
      />
    </el-sub-menu>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import {
  Dashboard,
  User,
  List,
  Setting,
  Document,
  Folder,
  Monitor,
  Key,
  Management,
  Film,
  Tools,
  Warning
} from '@element-plus/icons-vue'

const props = defineProps({
  menuItem: {
    type: Object,
    required: true
  }
})

const hasChildren = computed(() => {
  return props.menuItem.children && props.menuItem.children.length > 0
})

const iconComponents = {
  dashboard: Dashboard,
  user: User,
  list: List,
  role: Key,
  permission: Management,
  department: Management,
  content: Document,
  article: Document,
  category: Folder,
  media: Film,
  setting: Setting,
  config: Tools,
  log: Monitor,
  operation: List,
  error: Warning
}

const getIconComponent = (iconName) => {
  return iconComponents[iconName] || Document
}

const handleClick = () => {
  // 可以在这里添加额外的点击处理逻辑
}
</script>'''

    def generate_react_antd_menu(self, menu_data: List[Dict]) -> str:
        """生成React + Ant Design菜单组件"""
        return f'''import React, {{ useState, useEffect }} from 'react';
import {{ Menu }} from 'antd';
import {{ useNavigate, useLocation }} from 'react-router-dom';
import {{
  DashboardOutlined,
  UserOutlined,
  UnorderedListOutlined,
  SettingOutlined,
  FileTextOutlined,
  FolderOutlined,
  MonitorOutlined,
  KeyOutlined,
  TeamOutlined,
  PictureOutlined,
  ToolOutlined,
  WarningOutlined
}} from '@ant-design/icons';

const iconMap = {{
  dashboard: <DashboardOutlined />,
  user: <UserOutlined />,
  list: <UnorderedListOutlined />,
  role: <KeyOutlined />,
  permission: <TeamOutlined />,
  department: <TeamOutlined />,
  content: <FileTextOutlined />,
  article: <FileTextOutlined />,
  category: <FolderOutlined />,
  media: <PictureOutlined />,
  setting: <SettingOutlined />,
  config: <ToolOutlined />,
  log: <MonitorOutlined />,
  operation: <UnorderedListOutlined />,
  error: <WarningOutlined />
}};

const menuData = {json.dumps(menu_data, ensure_ascii=False, indent=2)};

const SidebarMenu = ({{ collapsed = false }}) => {{
  const navigate = useNavigate();
  const location = useLocation();
  const [selectedKeys, setSelectedKeys] = useState([location.pathname]);
  const [openKeys, setOpenKeys] = useState([]);

  useEffect(() => {{
    setSelectedKeys([location.pathname]);
    
    // 自动展开包含当前路径的菜单
    const pathParts = location.pathname.split('/').filter(Boolean);
    const openKeysList = [];
    for (let i = 1; i <= pathParts.length; i++) {{
      openKeysList.push('/' + pathParts.slice(0, i).join('/'));
    }}
    setOpenKeys(openKeysList);
  }}, [location.pathname]);

  const renderMenuItem = (item) => {{
    if (item.children && item.children.length > 0) {{
      return (
        <Menu.SubMenu
          key={{item.path}}
          icon={{iconMap[item.icon]}}
          title={{item.title}}
        >
          {{item.children.map(child => renderMenuItem(child))}}
        </Menu.SubMenu>
      );
    }}

    return (
      <Menu.Item
        key={{item.path}}
        icon={{iconMap[item.icon]}}
        onClick={{() => navigate(item.path)}}
      >
        {{item.title}}
      </Menu.Item>
    );
  }};

  return (
    <div className="sidebar-menu" style={{{{ height: '100vh', overflow: 'auto' }}}}>
      <Menu
        mode="inline"
        theme="{self.config.theme}"
        selectedKeys={{selectedKeys}}
        openKeys={{openKeys}}
        onOpenChange={{setOpenKeys}}
        inlineCollapsed={{collapsed}}
        style={{{{ height: '100%', borderRight: 0 }}}}
      >
        {{menuData.map(item => renderMenuItem(item))}}
      </Menu>
    </div>
  );
}};

export default SidebarMenu;'''

    def generate_typescript_definitions(self) -> str:
        """生成TypeScript类型定义"""
        return '''export interface MenuItem {
  id: number;
  title: string;
  path: string;
  icon?: string;
  children?: MenuItem[];
  meta?: {
    title?: string;
    requiresAuth?: boolean;
    roles?: string[];
    permissions?: string[];
    hidden?: boolean;
  };
}

export interface MenuConfig {
  collapsed: boolean;
  theme: 'light' | 'dark';
  width: number;
  enableSearch: boolean;
}

export interface RouteConfig {
  path: string;
  name: string;
  component: string;
  meta?: {
    title: string;
    icon?: string;
    requiresAuth?: boolean;
    roles?: string[];
    permissions?: string[];
    hidden?: boolean;
  };
  children?: RouteConfig[];
}

// 工具函数
export const findMenuByPath = (menus: MenuItem[], path: string): MenuItem | null => {
  for (const menu of menus) {
    if (menu.path === path) {
      return menu;
    }
    if (menu.children) {
      const found = findMenuByPath(menu.children, path);
      if (found) return found;
    }
  }
  return null;
};

export const getMenuPaths = (menus: MenuItem[]): string[] => {
  const paths: string[] = [];
  menus.forEach(menu => {
    paths.push(menu.path);
    if (menu.children) {
      paths.push(...getMenuPaths(menu.children));
    }
  });
  return paths;
};

export const filterMenusByRole = (menus: MenuItem[], userRoles: string[]): MenuItem[] => {
  return menus.filter(menu => {
    if (menu.meta?.roles && !menu.meta.roles.some(role => userRoles.includes(role))) {
      return false;
    }
    if (menu.children) {
      menu.children = filterMenusByRole(menu.children, userRoles);
    }
    return true;
  });
};'''

    def generate_router_config(self, menu_data: List[Dict]) -> str:
        """生成路由配置"""
        routes = []
        
        def extract_routes(menus: List[Dict], parent_path: str = ""):
            for menu in menus:
                route = {
                    "path": menu["path"],
                    "name": self._path_to_component_name(menu["path"]),
                    "component": f"() => import('@/views{menu['path']}/index.vue')",
                    "meta": {
                        "title": menu["title"],
                        "icon": menu.get("icon"),
                        "requiresAuth": True
                    }
                }
                routes.append(route)
                
                if menu.get("children"):
                    extract_routes(menu["children"], menu["path"])
        
        extract_routes(menu_data)
        
        return f'''import {{ createRouter, createWebHistory, RouteRecordRaw }} from 'vue-router'

const routes: RouteRecordRaw[] = {json.dumps(routes, ensure_ascii=False, indent=2).replace('"() => import', '() => import').replace(')"', ')')}

const router = createRouter({{
  history: createWebHistory(process.env.BASE_URL),
  routes,
  scrollBehavior: () => ({{ top: 0 }})
}})

// 路由守卫
router.beforeEach(async (to, from, next) => {{
  // 这里可以添加认证逻辑
  const requiresAuth = to.matched.some(record => record.meta?.requiresAuth)
  
  if (requiresAuth) {{
    // 检查用户是否已登录
    const token = localStorage.getItem('token')
    if (!token) {{
      next('/login')
      return
    }}
  }}
  
  next()
}})

export default router'''

    def _path_to_component_name(self, path: str) -> str:
        """将路径转换为组件名称"""
        parts = path.strip('/').split('/')
        return ''.join(word.capitalize() for word in parts if word)
    
    def _get_bg_color(self) -> str:
        return "#ffffff" if self.config.theme == "light" else "#001529"
    
    def _get_text_color(self) -> str:
        return "#303133" if self.config.theme == "light" else "rgba(255, 255, 255, 0.65)"
    
    def _get_active_color(self) -> str:
        return "#409EFF" if self.config.theme == "light" else "#1890ff"

    def generate_readme(self) -> str:
        """生成README文档"""
        return f'''# 通用三级左侧菜单组件

这是一个通用的三级左侧菜单组件，支持多种前端框架。

## 特性

- 🎯 标准三级菜单结构
- 🎨 支持多种UI框架 (Element Plus, Ant Design, Material)
- 📱 响应式设计
- 🔍 可选搜索功能
- 🎭 主题切换支持
- 🔐 权限控制集成
- 📦 TypeScript支持

## 菜单数据结构

```typescript
interface MenuItem {{
  id: number;           // 唯一标识
  title: string;        // 菜单标题
  path: string;         // 路由路径
  icon?: string;        // 图标名称
  children?: MenuItem[]; // 子菜单（最多3级）
  meta?: {{              // 元信息
    requiresAuth?: boolean;
    roles?: string[];
    hidden?: boolean;
  }};
}}
```

## 使用方法

### Vue 3 + Element Plus

```vue
<template>
  <SidebarMenu :collapse="collapsed" />
</template>

<script setup>
import SidebarMenu from './components/SidebarMenu.vue'
import {{ ref }} from 'vue'

const collapsed = ref(false)
</script>
```

### React + Ant Design

```jsx
import SidebarMenu from './components/SidebarMenu'

function App() {{
  const [collapsed, setCollapsed] = useState(false)
  
  return (
    <SidebarMenu collapsed={{collapsed}} />
  )
}}
```

## 配置选项

- `framework`: 目标框架 (vue_element, react_antd)
- `theme`: 主题 (light, dark)
- `enableIcons`: 是否启用图标
- `enableCollapse`: 是否支持折叠
- `enableSearch`: 是否启用搜索
- `maxLevels`: 最大层级数 (默认3级)

## 图标映射

支持常用图标的自动映射：

- dashboard → 仪表盘图标
- user → 用户图标
- setting → 设置图标
- content → 内容图标
- list → 列表图标

## 权限控制

支持基于角色和权限的菜单过滤：

```typescript
const filteredMenus = filterMenusByRole(menus, userRoles)
```

## 自定义样式

可以通过CSS变量自定义主题：

```css
:root {{
  --sidebar-width: 240px;
  --sidebar-bg-color: #ffffff;
  --sidebar-text-color: #303133;
  --sidebar-active-color: #409EFF;
}}
```

## 生成配置

使用 `UniversalMenuGenerator` 生成组件：

```python
from universal_menu_generator import UniversalMenuGenerator, UniversalMenuConfig, FrameworkType

config = UniversalMenuConfig(
    framework=FrameworkType.VUE_ELEMENT,
    theme="light",
    enable_icons=True,
    enable_collapse=True
)

generator = UniversalMenuGenerator(config)
generator.generate_complete_project()
```
'''

    def generate_complete_project(self, output_dir: str = None):
        """生成完整项目"""
        if output_dir is None:
            output_dir = self.config.output_dir
            
        os.makedirs(output_dir, exist_ok=True)
        
        # 生成示例数据
        menu_data = self.create_sample_data()
        
        # 保存菜单数据
        with open(os.path.join(output_dir, 'menuData.json'), 'w', encoding='utf-8') as f:
            json.dump(menu_data, f, ensure_ascii=False, indent=2)
        
        # 生成TypeScript定义
        with open(os.path.join(output_dir, 'types.ts'), 'w', encoding='utf-8') as f:
            f.write(self.generate_typescript_definitions())
        
        # 根据框架生成对应组件
        if self.config.framework == FrameworkType.VUE_ELEMENT:
            self._generate_vue_project(output_dir, menu_data)
        elif self.config.framework == FrameworkType.REACT_ANTD:
            self._generate_react_project(output_dir, menu_data)
        
        # 生成README
        with open(os.path.join(output_dir, 'README.md'), 'w', encoding='utf-8') as f:
            f.write(self.generate_readme())
        
        print(f"✅ 通用菜单项目生成完成！")
        print(f"📁 输出目录: {output_dir}")
        print(f"🎯 框架: {self.config.framework.value}")
        print(f"📊 菜单项数量: {self._count_menu_items(menu_data)}")
        
    def _generate_vue_project(self, output_dir: str, menu_data: List[Dict]):
        """生成Vue项目文件"""
        # 主菜单组件
        with open(os.path.join(output_dir, 'SidebarMenu.vue'), 'w', encoding='utf-8') as f:
            f.write(self.generate_vue_element_menu(menu_data))
        
        # 菜单项组件
        with open(os.path.join(output_dir, 'SidebarMenuItem.vue'), 'w', encoding='utf-8') as f:
            f.write(self.generate_vue_menu_item())
        
        # 路由配置
        with open(os.path.join(output_dir, 'router.ts'), 'w', encoding='utf-8') as f:
            f.write(self.generate_router_config(menu_data))
    
    def _generate_react_project(self, output_dir: str, menu_data: List[Dict]):
        """生成React项目文件"""
        with open(os.path.join(output_dir, 'SidebarMenu.jsx'), 'w', encoding='utf-8') as f:
            f.write(self.generate_react_antd_menu(menu_data))
    
    def _count_menu_items(self, menus: List[Dict]) -> int:
        """统计菜单项数量"""
        count = len(menus)
        for menu in menus:
            if menu.get('children'):
                count += self._count_menu_items(menu['children'])
        return count

def main():
    """主函数"""
    print("🚀 通用三级左侧菜单生成器")
    print("=" * 50)
    
    # 生成Vue版本
    vue_config = UniversalMenuConfig(
        framework=FrameworkType.VUE_ELEMENT,
        output_dir="universal_sidebar_menu/vue",
        theme="light",
        enable_icons=True,
        enable_collapse=True,
        enable_search=False
    )
    
    # 生成React版本
    react_config = UniversalMenuConfig(
        framework=FrameworkType.REACT_ANTD,
        output_dir="universal_sidebar_menu/react",
        theme="dark",
        enable_icons=True,
        enable_collapse=True,
        enable_search=True
    )
    
    print("🎯 生成Vue 3 + Element Plus版本...")
    vue_generator = UniversalMenuGenerator(vue_config)
    vue_generator.generate_complete_project()
    
    print("\n🎯 生成React + Ant Design版本...")
    react_generator = UniversalMenuGenerator(react_config)
    react_generator.generate_complete_project()
    
    print("\n🎉 两个框架版本生成完成！")
    print("📁 Vue版本: universal_sidebar_menu/vue/")
    print("📁 React版本: universal_sidebar_menu/react/")
    print("\n💡 可以直接在项目中使用生成的组件。")

if __name__ == "__main__":
    main()
